home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / adaed / nyudemos / diners2.ada < prev    next >
Encoding:
Text File  |  1996-01-30  |  12.1 KB  |  439 lines

  1. --::::::::::
  2. --screen.ads
  3. --::::::::::
  4. PACKAGE Screen IS
  5.  
  6. -- Procedures for drawing pictures on ANSI Terminal Screen
  7.  
  8.   ScreenDepth : CONSTANT Integer := 24;
  9.   ScreenWidth : CONSTANT Integer := 80;
  10.  
  11.   SUBTYPE Depth IS Integer RANGE 1..ScreenDepth;
  12.   SUBTYPE Width IS Integer RANGE 1..ScreenWidth;
  13.  
  14.   PROCEDURE Beep; 
  15.   PROCEDURE ClearScreen; 
  16.   PROCEDURE MoveCursor (Column : Width; Row : Depth);
  17.  
  18. END Screen;   
  19. --::::::::::
  20. --windows.ads
  21. --::::::::::
  22. WITH Screen;
  23. USE Screen;
  24. PACKAGE Windows IS
  25.  
  26.   TYPE Window IS PRIVATE;
  27.  
  28.   PROCEDURE Open (W      : IN OUT Window; -- Window variable returned 
  29.                   Row    : Depth; -- Upper left corner
  30.                   Column : Width;
  31.                   Height : Depth; -- Size of window
  32.                   Width  : Screen.Width);
  33.  
  34.   -- Create a window variable and open the window for writing.  
  35.   -- No checks for overlap of windows are made. 
  36.  
  37.  
  38.   PROCEDURE Close (W : IN OUT Window);
  39.   -- Close window and clear window variable. 
  40.  
  41.  
  42.   PROCEDURE Title (W     : IN OUT Window;
  43.                    Name  : String;
  44.                    Under : Character);
  45.  
  46.   -- Put a title name at the top of the window.  If the parameter 
  47.   -- under <> 0C or ' ', underline the title with the specified character. 
  48.  
  49.  
  50.   PROCEDURE Borders (W                    : IN OUT Window;
  51.                      Corner, Down, Across : Character);
  52.  
  53.   -- Draw border around current writable area in window with characters
  54.   -- specified.  Call this BEFORE Title.  
  55.  
  56.  
  57.   PROCEDURE Gotorowcolumn (W      : IN OUT Window;
  58.                            Row    : Depth;
  59.                            Column : Width);
  60.  
  61.   -- Goto the row and column specified.  Coordinates are relative to the
  62.   -- upper left corner of window, which is (1, 1) 
  63.  
  64.  
  65.   PROCEDURE Put (W  : IN OUT Window;
  66.                  Ch : Character);
  67.  
  68.   -- put one character to the window.
  69.   -- If end of column, go to the next row.
  70.   -- If end of window, go to the top of the window. 
  71.  
  72.  
  73.   PROCEDURE Put_String (W : IN OUT Window;
  74.                         S : String);
  75.  
  76.   -- put a string to window. 
  77.  
  78.  
  79.   PROCEDURE New_Line (W : IN OUT Window);
  80.  
  81.   -- Go to beginning of next line.  Next line is
  82.   -- not blanked until next character is written  
  83.  
  84.  
  85. PRIVATE
  86.   TYPE Window IS
  87.     RECORD
  88.       Currentrow, -- Current cursor row 
  89.       Firstrow,
  90.       Lastrow : Depth;
  91.       Currentcolumn, -- Current cursor column 
  92.       Firstcolumn,
  93.       Lastcolumn : Width;
  94.     END RECORD;
  95.  
  96. END Windows;
  97. --::::::::::
  98. --screen.adb
  99. --::::::::::
  100. WITH Text_IO;
  101. WITH My_Int_IO;
  102. PACKAGE BODY Screen IS
  103.  
  104. -- Procedures for drawing pictures on ANSI Terminal Screen
  105.  
  106.  
  107.   PROCEDURE Beep IS
  108.   BEGIN
  109.     Text_IO.Put (Item => ASCII.BEL);
  110.   END Beep;
  111.  
  112.   PROCEDURE ClearScreen IS
  113.   BEGIN
  114.     Text_IO.Put (Item => ASCII.ESC);
  115.     Text_IO.Put (Item => "[2J");
  116.   END ClearScreen;
  117.  
  118.   PROCEDURE MoveCursor (Column : Width; Row : Depth) IS
  119.   BEGIN                                                
  120.     Text_IO.New_Line;
  121.     Text_IO.Put (Item => ASCII.ESC);
  122.     Text_IO.Put ("[");
  123.     My_Int_IO.Put (Item => Row, Width => 1);
  124.     Text_IO.Put (Item => ';');
  125.     My_Int_IO.Put (Item => Column, Width => 1);
  126.     Text_IO.Put (Item => 'f');
  127.   END MoveCursor;  
  128.  
  129. END Screen;
  130. --::::::::::
  131. --windows.adb
  132. --::::::::::
  133. WITH Text_IO, My_Int_IO, Screen;
  134. USE Text_IO, My_Int_IO, Screen;
  135. PACKAGE BODY Windows IS
  136.  
  137.   CursorRow : Depth := 1; -- Current cursor position
  138.   CursorCol : Width := 1;
  139.  
  140.   PROCEDURE Open (W      : IN OUT Window;
  141.                   Row    : Depth;
  142.                   Column : Width;
  143.                   Height : Depth;
  144.                   Width  : Screen.Width) IS
  145.     --Put the Window's cursor in upper left corner
  146.   BEGIN
  147.     W.CurrentRow    := Row;
  148.     W.FirstRow      := Row;
  149.     W.LastRow       := Row + Height - 1;
  150.     W.CurrentColumn := Column;
  151.     W.FirstColumn   := Column;
  152.     W.LastColumn    := Column + Width - 1;
  153.   END Open;
  154.  
  155.   PROCEDURE Close (W : IN OUT Window) IS
  156.   BEGIN
  157.     NULL;
  158.   END Close;
  159.  
  160.   PROCEDURE Title (W     : IN OUT Window;
  161.                    name  : String;
  162.                    under : CHARACTER) IS
  163.     -- Put name at the top of the Window.  If under <>  ' ', underline
  164.     -- the title. 
  165.     i : Width;
  166.   BEGIN
  167.     -- Put name on top line
  168.     W.CurrentColumn := W.FirstColumn;
  169.     W.CurrentRow    := W.FirstRow;
  170.     Put_String (w, name);
  171.     new_line (w);
  172.     -- Underline name if desired, and move the First line of the Window
  173.     -- below the title 
  174.     IF under = ' ' THEN
  175.       W.FirstRow := W.FirstRow + 1;
  176.     ELSE
  177.       FOR i IN W.FirstColumn .. W.LastColumn LOOP
  178.         Put (w, under);
  179.       END LOOP;
  180.       new_line (w);
  181.       W.FirstRow := W.FirstRow + 2;
  182.     END IF;
  183.   END Title;
  184.  
  185.  
  186.   PROCEDURE GotoRowColumn (w      : IN OUT Window;
  187.                            Row    : Depth;
  188.                            Column : Width) IS
  189.     -- Relative to writable Window boundaries, of course
  190.   BEGIN
  191.     W.CurrentRow    := W.FirstRow + Row;
  192.     W.CurrentColumn := W.FirstColumn + Column;
  193.   END GotoRowColumn;
  194.  
  195.  
  196.   PROCEDURE Borders (w                    : IN OUT Window;
  197.                      corner, down, across : CHARACTER) IS
  198.     -- Draw border around current writable area in Window with characters.
  199.     -- Call this BEFORE Title.  
  200.     i : Depth;
  201.     j : Width;
  202.   BEGIN
  203.     -- Put top line of border
  204.     MoveCursor (W.FirstColumn, W.FirstRow);
  205.     Text_IO.Put (corner);
  206.     FOR j IN W.FirstColumn + 1 .. W.LastColumn - 1 LOOP
  207.       Text_IO.Put (across);
  208.     END LOOP;
  209.     Text_IO.Put (corner);
  210.  
  211.     -- Put the two side lines
  212.     FOR i IN W.FirstRow + 1 .. W.LastRow - 1 LOOP
  213.       MoveCursor (W.FirstColumn, i);
  214.       Text_IO.Put (down);
  215.       MoveCursor (W.LastColumn, i);
  216.       Text_IO.Put (down);
  217.     END LOOP;
  218.  
  219.     -- Put the bottom line of the border
  220.     MoveCursor (W.FirstColumn, W.LastRow);
  221.     Text_IO.Put (corner);
  222.     FOR j IN W.FirstColumn + 1 .. W.LastColumn - 1 LOOP
  223.       Text_IO.Put (across);
  224.     END LOOP;
  225.     Text_IO.Put (corner);
  226.  
  227.     -- Put the cursor at the very end of the Window
  228.     CursorRow := W.LastRow;
  229.     CursorCol := W.LastColumn + 1;
  230.  
  231.     -- Make the Window smaller by one character on each side
  232.     W.FirstRow      := W.FirstRow + 1;
  233.     W.CurrentRow    := W.FirstRow;
  234.     W.LastRow       := W.LastRow - 1;
  235.     W.FirstColumn   := W.FirstColumn + 1;
  236.     W.CurrentColumn := W.FirstColumn;
  237.     W.LastColumn    := W.LastColumn - 1;
  238.   END Borders;
  239.  
  240.  
  241.   PROCEDURE EraseToEndOfLine (W : IN OUT Window) IS
  242.     i : Width;
  243.   BEGIN
  244.     MoveCursor (W.CurrentColumn, W.CurrentRow);
  245.     FOR i IN W.CurrentColumn .. W.LastColumn LOOP
  246.       Text_IO.Put (' ');
  247.     END LOOP;
  248.     MoveCursor (W.CurrentColumn, W.CurrentRow);
  249.     CursorCol := W.CurrentColumn;
  250.     CursorRow := W.CurrentRow;
  251.   END EraseToEndOfLine;
  252.  
  253.  
  254.   PROCEDURE Put (W  : IN OUT Window;
  255.                  ch : CHARACTER) IS
  256.  
  257.     -- If after end of line, move to First character of next line
  258.     -- If about to write First character on line, blank rest of line.
  259.     -- Put character.
  260.  
  261.   BEGIN
  262.     IF Ch = ASCII.CR THEN
  263.       New_Line (W);
  264.       RETURN;
  265.     END IF;
  266.  
  267.     -- If at end of current line, move to next line 
  268.     IF W.CurrentColumn > W.LastColumn THEN
  269.       IF W.CurrentRow = W.LastRow THEN
  270.         W.CurrentRow := W.FirstRow;
  271.       ELSE
  272.         W.CurrentRow := W.CurrentRow + 1;
  273.       END IF;
  274.       W.CurrentColumn := W.FirstColumn;
  275.     END IF;
  276.  
  277.     -- If at W.First char, erase line
  278.     IF W.CurrentColumn = W.FirstColumn THEN
  279.       EraseToEndOfLine (W);
  280.     END IF;
  281.  
  282.     -- Put physical cursor at Window's cursor
  283.     IF (CursorCol /= W.CurrentColumn) OR (CursorRow /= W.CurrentRow) THEN
  284.       MoveCursor (W.CurrentColumn, W.CurrentRow);
  285.       CursorRow := W.CurrentRow;
  286.     END IF;
  287.  
  288.     IF Ch = ASCII.BS THEN
  289.       -- Special backspace handling 
  290.       IF W.CurrentColumn /= W.FirstColumn THEN
  291.         Text_IO.Put (Ch);
  292.         W.CurrentColumn := W.CurrentColumn - 1;
  293.       END IF;
  294.     ELSE
  295.       Text_IO.Put (Ch);
  296.       W.CurrentColumn := W.CurrentColumn + 1;
  297.     END IF;
  298.     CursorCol := W.CurrentColumn;
  299.   END Put;
  300.  
  301.  
  302.   PROCEDURE new_line (W : IN OUT Window) IS
  303.     col : Width;
  304.  
  305.     -- If not after line, blank rest of line.
  306.     -- Move to First character of next line
  307.  
  308.   BEGIN
  309.     IF W.CurrentColumn = 0 THEN
  310.       EraseToEndOfLine (W);
  311.     END IF;
  312.     IF W.CurrentRow = W.LastRow THEN
  313.       W.CurrentRow := W.FirstRow;
  314.     ELSE
  315.       W.CurrentRow := W.CurrentRow + 1;
  316.     END IF;
  317.     W.CurrentColumn := W.FirstColumn;
  318.   END new_line;
  319.  
  320.  
  321.   PROCEDURE Put_String (W : IN OUT Window;
  322.                         S : String) IS
  323.   BEGIN
  324.     FOR I IN S'FIRST .. S'LAST LOOP
  325.       Put (W, S (i));
  326.     END LOOP;
  327.   END Put_String;
  328.  
  329.  
  330. BEGIN -- Windows
  331.   ClearScreen;
  332.   MoveCursor (1, 1);
  333. END Windows;
  334. --::::::::::
  335. --roomwind.adb
  336. --::::::::::
  337. WITH Windows;
  338. WITH Chop;
  339. WITH Phil;
  340. WITH Calendar; 
  341. PRAGMA Elaborate(Phil);
  342. PACKAGE BODY Room IS
  343.  
  344.   Phils:      ARRAY(Table_Type) OF Phil.Philosopher;
  345.   Phil_Windows: ARRAY(Table_Type) OF Windows.Window;
  346.  
  347.   TYPE Phil_Names IS (Dijkstra, Texel, Booch, Ichbiah, Stroustrup);
  348.  
  349.   TASK BODY Head_Waiter IS
  350.  
  351.     T : Integer; 
  352.     Start_Time: Calendar.Time;
  353.  
  354.   BEGIN
  355.  
  356.     ACCEPT Open_The_Room;
  357.     Start_Time := Calendar.Clock;
  358.  
  359.     Windows.Open(Phil_Windows(1),1,23,7,30);
  360.     Windows.Borders(Phil_Windows(1),'+','|','-');
  361.     Windows.Title(Phil_Windows(1), "Eddy Dijkstra",'-');
  362.     Phils(1).Come_To_Life(1,1,2);
  363.  
  364.     Windows.Open(Phil_Windows(3),9,50,7,30); 
  365.     Windows.Borders(Phil_Windows(3),'+','|','-');
  366.     Windows.Title(Phil_Windows(3), "Grady Booch",'-');
  367.     Phils(3).Come_To_Life(3,3,4);
  368.  
  369.     Windows.Open(Phil_Windows(2),9,2,7,30); 
  370.     Windows.Borders(Phil_Windows(2),'+','|','-');
  371.     Windows.Title(Phil_Windows(2), "Putnam Texel",'-');
  372.     Phils(2).Come_To_Life(2,2,3);
  373.  
  374.     Windows.Open(Phil_Windows(5),17,41,7,30); 
  375.     Windows.Borders(Phil_Windows(5),'+','|','-');
  376.     Windows.Title(Phil_Windows(5), "Bjarne Stroustrup",'-');
  377.     Phils(5).Come_To_Life(5,1,5);
  378.  
  379.     Windows.Open(Phil_Windows(4),17,8,7,30); 
  380.     Windows.Borders(Phil_Windows(4),'+','|','-');
  381.     Windows.Title(Phil_Windows(4), "Jean Ichbiah",'-');
  382.     Phils(4).Come_To_Life(4,4,5);
  383.  
  384.     LOOP
  385.       SELECT
  386.         ACCEPT Report_State(Which_Phil: Table_Type;
  387.                          State: Phil.States;
  388.                          How_Long: Natural := 0) DO
  389.           T := Integer(Calendar."-"(Calendar.Clock,Start_Time));
  390.           Windows.Put_String(Phil_Windows(Which_Phil),
  391.             "T=" & Integer'Image(T) & " ");
  392.           CASE State IS
  393.             WHEN Phil.Breathing =>
  394.               Windows.Put_String(Phil_Windows(Which_Phil), "Breathing...");
  395.               Windows.New_Line(Phil_Windows(Which_Phil));
  396.  
  397.             WHEN Phil.Thinking =>
  398.               Windows.Put_String(Phil_Windows(Which_Phil),
  399.                          "Thinking"
  400.                          & Integer'Image(How_Long)
  401.                          & " seconds.");
  402.               Windows.New_Line(Phil_Windows(Which_Phil));
  403.  
  404.             WHEN Phil.Eating =>
  405.               Windows.Put_String(Phil_Windows(Which_Phil),
  406.                          "Eating"   
  407.                          & Integer'Image(How_Long)
  408.                          & " seconds.");
  409.               Windows.New_Line(Phil_Windows(Which_Phil));
  410.  
  411.             WHEN Phil.Done_Eating =>
  412.               Windows.Put_String(Phil_Windows(Which_Phil), "Yum-yum (burp)");
  413.               Windows.New_Line(Phil_Windows(Which_Phil));
  414.  
  415.             WHEN Phil.Got_One_Stick =>
  416.               Windows.Put_String(Phil_Windows(Which_Phil), 
  417.                          "First chopstick"
  418.                           & Integer'Image(How_Long));
  419.               Windows.New_Line(Phil_Windows(Which_Phil));
  420.  
  421.             WHEN Phil.Got_Other_Stick =>
  422.               Windows.Put_String(Phil_Windows(Which_Phil), 
  423.                          "Second chopstick"
  424.                           & Integer'Image(How_Long));
  425.               Windows.New_Line(Phil_Windows(Which_Phil));
  426.  
  427.           END CASE;
  428.  
  429.          END Report_State;
  430.         OR
  431.           TERMINATE;
  432.         END SELECT;
  433.  
  434.       END LOOP;
  435.  
  436.     END Head_Waiter;
  437.  
  438. END Room;
  439.